# -*- coding:utf-8 -*-
import numpy as np
import random
import time

from sklearn.neighbors import KNeighborsClassifier
# 特征提取方法 + KNN分类器

from preprocess_data import get_data
class forward_search(object):
	"""docstring for forward_search"""
	def __init__(self, n_neighbors = 5,valid_num = 200):
		super(forward_search, self).__init__()
		features,labels = get_data('训练集')
		test_features,test_labels = get_data('测试集')
		features_mean = features.mean(axis = 0,keepdims = True)
		features_std = features.std(axis = 0,keepdims = True)
		features = (features - features_mean)/(features_std+1e-8) # 利用广播机制
		test_features = (test_features - features_mean)/(features_std+1e-8)

		train_features = features[:-valid_num]
		train_labels = labels[:-valid_num]
		valid_features = features[-valid_num:]
		valid_labels = labels[-valid_num:]

		# 搜索法
		# 选用前向搜索
		feature = []
		best_score_pre = 0
		for k in range(440):
			best_i = -1
			best_score = 0
			t = time.time()
			for i in range(440):
				if i in feature: continue
				# 挑选特征
				feature.append(i)
				clf = KNeighborsClassifier(n_neighbors=n_neighbors)
				clf.fit(train_features.take(feature,axis=1), train_labels) # 挑选特征
				score = clf.score(valid_features.take(feature,axis=1),valid_labels)
				if (i+1)%100 == 0:
					print('i:%d,score:%.2f'%(i+1,score))
				if score>best_score:
					best_score = score
					best_i = i
				feature.pop()
			feature.append(best_i)
			end_t = time.time()

			# 再在测试集上测试
			clf = KNeighborsClassifier(n_neighbors=n_neighbors)
			clf.fit(train_features.take(feature,axis=1), train_labels) # 挑选特征
			test_time = time.time()
			score = clf.score(test_features.take(feature,axis=1),test_labels)

			print('[epoch] %d'%k)
			print('[time] %.2f'%(end_t-t))
			print('[valid] best_i:%d,score:%.2f'%(best_i,best_score))
			print('[test ] score:%.2f,test_time:%.2f'%(score,time.time()-test_time))
			if best_score < best_score_pre:
				break
			best_score_pre = best_score
		self.feature = feature

	def get_feature(self,n_feature=440):
		n_feature = min(n_feature,len(self.feature))
		return self.feature[:n_feature]